/**
 * 性能优化工具函数
 * 包含防抖、节流等常用性能优化函数
 */

/**
 * 防抖函数
 * @param {Function} func - 要防抖的函数
 * @param {number} wait - 等待时间（毫秒）
 * @param {boolean} immediate - 是否立即执行
 * @returns {Function} 防抖后的函数
 */
export function debounce(func, wait = 300, immediate = false) {
  let timeout;
  
  return function executedFunction(...args) {
    const later = () => {
      timeout = null;
      if (!immediate) func.apply(this, args);
    };
    
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    
    if (callNow) func.apply(this, args);
  };
}

/**
 * 节流函数
 * @param {Function} func - 要节流的函数
 * @param {number} limit - 限制时间（毫秒）
 * @returns {Function} 节流后的函数
 */
export function throttle(func, limit = 300) {
  let inThrottle;
  
  return function(...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

/**
 * 高级节流函数（支持首次立即执行）
 * @param {Function} func - 要节流的函数
 * @param {number} wait - 等待时间（毫秒）
 * @param {Object} options - 配置选项
 * @returns {Function} 节流后的函数
 */
export function throttleAdvanced(func, wait = 300, options = {}) {
  let timeout, context, args, result;
  let previous = 0;
  
  const later = function() {
    previous = options.leading === false ? 0 : Date.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };
  
  return function(...args) {
    const now = Date.now();
    if (!previous && options.leading === false) previous = now;
    
    const remaining = wait - (now - previous);
    context = this;
    args = arguments;
    
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
    
    return result;
  };
}

/**
 * 记忆化函数（缓存函数结果）
 * @param {Function} func - 要记忆化的函数
 * @returns {Function} 记忆化后的函数
 */
export function memoize(func) {
  const cache = new Map();
  
  return function(...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) {
      return cache.get(key);
    }
    
    const result = func.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

/**
 * 异步防抖函数
 * @param {Function} func - 要防抖的异步函数
 * @param {number} wait - 等待时间（毫秒）
 * @returns {Function} 防抖后的异步函数
 */
export function asyncDebounce(func, wait = 300) {
  let timeout;
  
  return function(...args) {
    return new Promise((resolve, reject) => {
      clearTimeout(timeout);
      
      timeout = setTimeout(async () => {
        try {
          const result = await func.apply(this, args);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      }, wait);
    });
  };
}

/**
 * 异步节流函数
 * @param {Function} func - 要节流的异步函数
 * @param {number} limit - 限制时间（毫秒）
 * @returns {Function} 节流后的异步函数
 */
export function asyncThrottle(func, limit = 300) {
  let inThrottle = false;
  let lastResult;
  
  return function(...args) {
    return new Promise((resolve, reject) => {
      if (inThrottle) {
        resolve(lastResult);
        return;
      }
      
      inThrottle = true;
      
      func.apply(this, args)
        .then(result => {
          lastResult = result;
          resolve(result);
        })
        .catch(error => {
          reject(error);
        })
        .finally(() => {
          setTimeout(() => {
            inThrottle = false;
          }, limit);
        });
    });
  };
}

/**
 * 批量执行函数
 * @param {Array} tasks - 任务数组
 * @param {number} batchSize - 批次大小
 * @param {number} delay - 批次间延迟（毫秒）
 * @returns {Promise} 执行结果
 */
export function batchExecute(tasks, batchSize = 5, delay = 100) {
  return new Promise(async (resolve, reject) => {
    const results = [];
    
    try {
      for (let i = 0; i < tasks.length; i += batchSize) {
        const batch = tasks.slice(i, i + batchSize);
        const batchResults = await Promise.all(batch.map(task => task()));
        results.push(...batchResults);
        
        if (i + batchSize < tasks.length) {
          await new Promise(resolve => setTimeout(resolve, delay));
        }
      }
      
      resolve(results);
    } catch (error) {
      reject(error);
    }
  });
}

/**
 * 性能监控装饰器
 * @param {string} name - 监控名称
 * @returns {Function} 装饰器函数
 */
export function performanceMonitor(name) {
  return function(target, propertyKey, descriptor) {
    const originalMethod = descriptor.value;
    
    descriptor.value = function(...args) {
      const start = performance.now();
      const result = originalMethod.apply(this, args);
      const end = performance.now();
      
      console.log(`${name} 执行时间: ${end - start}ms`);
      
      return result;
    };
    
    return descriptor;
  };
}

/**
 * 延迟执行函数
 * @param {Function} func - 要延迟执行的函数
 * @param {number} delay - 延迟时间（毫秒）
 * @returns {Promise} 延迟执行的结果
 */
export function delay(func, delay = 1000) {
  return new Promise((resolve, reject) => {
    setTimeout(async () => {
      try {
        const result = await func();
        resolve(result);
      } catch (error) {
        reject(error);
      }
    }, delay);
  });
}

/**
 * 重试函数
 * @param {Function} func - 要重试的函数
 * @param {number} maxRetries - 最大重试次数
 * @param {number} delay - 重试间隔（毫秒）
 * @returns {Promise} 执行结果
 */
export function retry(func, maxRetries = 3, delay = 1000) {
  return new Promise(async (resolve, reject) => {
    let lastError;
    
    for (let i = 0; i <= maxRetries; i++) {
      try {
        const result = await func();
        resolve(result);
        return;
      } catch (error) {
        lastError = error;
        console.warn(`第 ${i + 1} 次重试失败:`, error);
        
        if (i < maxRetries) {
          await new Promise(resolve => setTimeout(resolve, delay));
        }
      }
    }
    
    reject(lastError);
  });
}

// 导出所有函数
export default {
  debounce,
  throttle,
  throttleAdvanced,
  memoize,
  asyncDebounce,
  asyncThrottle,
  batchExecute,
  performanceMonitor,
  delay,
  retry
}; 